﻿/******************************************************************************************
*                                                                                         *    
*                              Developed by Bruno Pires                                   *
*                                                                                         *
*                             email: bruno@blastersystems.com                             *
*                               web: www.blastersystems.com                               *
*                              blog: www.blastersystems.com/blog                          *
*                           twitter: brunoacpires                                         *
*                                                                                         *
*                      Software available under GNU LGPL License                          *
*                                                                                         *    
* *****************************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataValidator
{
    public enum TipoCartao
    {
        amex,
        visa,
        mastercard
    }

    public class CartaoCredito
    {
        public CartaoCredito()
        {

        }

        private bool ValidaTipoCartao(TipoCartao cartao, byte[] numero, int tamanho)
        {
            switch(cartao)
            {
               case TipoCartao.mastercard:
                    if (tamanho != 16)
                     return false;
                  if (numero[0] != 5 || numero[1] == 0 || numero[1] > 5)
                     return false;
                  break;

              case TipoCartao.visa:
                  if (tamanho != 16 && tamanho != 13)
                     return false;
                  if (numero[0] != 4)
                     return false;
                  break;

               case TipoCartao.amex:
                  if (tamanho != 15)
                     return false;
                  if (numero[0] != 3 || (numero[1] != 4 && numero[1] != 7))
                     return false;
                  break;
            }

            return true;
        }

        private bool ValidaNumero(byte[] numero,int tamanho)
        { 
            //Algoritmo de validação
            int sum = 0;
            for (int i = tamanho - 1; i >= 0; i--)
            {
                if (i % 2 == tamanho % 2)
                {
                    int n = numero[i] * 2;
                    sum += (n / 10) + (n % 10);
                }
                else
                    sum += numero[i];
            }
            return (sum % 10 == 0);
        }

        public bool IsValid(string numeroCartao, TipoCartao cartao)
        {
            byte[] numero = new byte[16]; // numbero para validar

            //Remove caracteres que não são numéricos
            int tamanho = 0;

            for (int i = 0; i < numeroCartao.Length; i++)
            {
                if (char.IsDigit(numeroCartao, i))
                {
                    if (tamanho == 16) return false; // o numero do cartão tem demasiados caracteres 
                    numero[tamanho++] = byte.Parse(numeroCartao[i].ToString());
                }
            }

            //primeira fase de validação - validar o formato do número introduzido
            if (ValidaTipoCartao(cartao, numero, tamanho))
            {
                //segunda fase de validação - validar com o MOD10 o número de cartão introduzido
                if (ValidaNumero(numero, tamanho))
                {
                    return true;
                }
            }
            
            return false;
        }
    }
}
